//
//  RegisterViewModel.swift
//  HinsLive
//
//  Created by haoxian on 2019/4/20.
//  Copyright © 2019 Hins. All rights reserved.
//

import Foundation
import RxSwift
import RxCocoa


class RegisterViewModel {
    
    let accountValid: Observable<(Bool, String)>
    let passwordValid: Observable<(Bool, String)>
    let repeatValid: Observable<(Bool, String)>
    let nameValid: Observable<(Bool, String)>
    let registerEnable: Observable<Bool>

    init(accountDriver: Driver<String>,
         passwordDriver: Driver<String>,
         repeatDriver: Driver<String>,
         nameDriver: Driver<String>) {
        
        accountValid = accountDriver.asObservable()
            .throttle(0.3, scheduler: MainScheduler.instance)
            .distinctUntilChanged()
            .flatMapLatest(RegisterViewModel.accountValidate)
            .share()

        passwordValid = passwordDriver.asObservable()
            .flatMapLatest(RegisterViewModel.passwordValidate)
            .share()
        
        repeatValid = Driver.combineLatest(passwordDriver, repeatDriver) { ($0, $1) }
            .asObservable()
            .flatMapLatest(RegisterViewModel.repeatValidate)
            .share()
        
        nameValid = nameDriver.asObservable()
            .flatMapLatest(RegisterViewModel.nameValidate)
            .share()
        
        registerEnable = Observable.combineLatest(accountValid, passwordValid, repeatValid, nameValid) { $0.0 && $1.0 && $2.0 && $3.0 }
    }
    
    var registerTap: ((String, String, String)) -> Observable<Event<UserInfo>> {
        return { args in
            return Network.register(RegisterRequest.build(args))
                .preDo(onNext: {  AccountManager.share.login(with: $0) })
                .observeOn(MainScheduler.asyncInstance)
        }
    }

}

private extension RegisterViewModel {
    
    static var accountValidate: (String) -> Observable<(Bool, String)> {
        return { account -> Observable<(Bool, String)> in
            if account.isEmpty { return .just((false, "账号不能为空")) }
            if account.count < 8 { return .just((false, "账号长度至少为8个字符")) }
            if let _ = account.rangeOfCharacter(from: CharacterSet.alphanumerics.inverted) {
                return .just((false, "只能是数字和字母的组合"))
            }
            
            return Network.registerValidate(RegisterValidateRequest.with { $0.account = account })
                .map { (event) -> (Bool, String) in
                    if let error = event.error {
                        if let e = error as? NetworkError {
                            return (false, e.localizedDescription)
                        } else {
                            return (false, error.localizedDescription)
                        }
                    }
                    return (true, "账号可用")
            }
        }
    }
    
    static var passwordValidate: (String) -> Observable<(Bool, String)> {
        return { password -> Observable<(Bool, String)> in
            if password.isEmpty { return .just((false, "密码不能为空")) }
            if password.count < 8 { return .just((false, "密码长度至少为8个字符")) }
            if let _ = password.rangeOfCharacter(from: CharacterSet.alphanumerics.inverted) {
                return .just((false, "只能是数字和字母的组合"))
            }
            return .just((true, ""))
        }
    }
    
    static var repeatValidate: (String, String) -> Observable<(Bool, String)> {
        return { (pwd, repeatPwd) -> Observable<(Bool, String)> in
            return pwd == repeatPwd ? .just((true, "")) : .just((false, "两次密码输入不相同"))
        }
    }
    
    static var nameValidate: (String) -> Observable<(Bool, String)> {
        return { name -> Observable<(Bool, String)> in
            if name.isEmpty { return .just((false, "名字不能为空")) }
            if let _ = name.rangeOfCharacter(from: CharacterSet.alphanumerics.inverted) {
                return .just((false, "只能是数字和字母的组合"))
            }
            return .just((true, ""))
        }
    }
    
}

private extension RegisterRequest {
    static func build(_ args: (String, String, String)) -> RegisterRequest {
        return RegisterRequest.with {
            $0.account = args.0
            $0.password = args.1
            $0.name = args.2
        }
    }
}
